type TargetContext = '_self' | '_parent' | '_blank' | '_top';

export const openWindow = (
  url: string,
  opts?: { target?: TargetContext; [key: string]: any }
) => {
  const { target = '_blank', ...others } = opts || {};
  window.open(
    url,
    target,
    Object.entries(others)
      .reduce((preValue: string[], curValue) => {
        const [key, value] = curValue;
        return [...preValue, `${key}=${value}`];
      }, [])
      .join(',')
  );
};

export const regexUrl = new RegExp(
  '^(?!mailto:)(?:(?:http|https|ftp)://)(?:\\S+(?::\\S*)?@)?(?:(?:(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[0-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))|localhost)(?::\\d{2,5})?(?:(/|\\?|#)[^\\s]*)?$',
  'i'
);
// 处理日期参数
export function addDateRange(params: any, dateRange: any[], propName?: string) {
  const search = params;
  search.params =
    typeof search.params === 'object' &&
    search.params !== null &&
    !Array.isArray(search.params)
      ? search.params
      : {};
  dateRange = Array.isArray(dateRange) ? dateRange : [];
  if (typeof propName === 'undefined') {
    search.params = {
      ...search.params,
      beginTime: dateRange[0],
      endTime: dateRange[1],
    };
  } else {
    search.params = {
      ...search.params,
      ...Object.fromEntries([
        [`begin${propName}`, dateRange[0]],
        [`end${propName}`, dateRange[1]],
      ]),
    };
  }
  return search;
}

/**
 * get请求 参数处理
 * @param {*} params  参数
 */
export function tansParams(params: any) {
  let result = '';
  const keys = Object.keys(params);
  keys.forEach((propName) => {
    const value = params[propName];
    const part = `${encodeURIComponent(propName)}=`;
    if (value !== null && typeof value !== 'undefined') {
      if (typeof value === 'object') {
        const vKeys = Object.keys(value);
        vKeys.forEach((key) => {
          if (value[key] !== null && typeof value[key] !== 'undefined') {
            const param = `${propName}[${key}]`;
            const subPart = `${encodeURIComponent(param)}=`;
            result += `${subPart + encodeURIComponent(value[key])}&`;
          }
        });
      } else {
        result += `${part + encodeURIComponent(value)}&`;
      }
    }
  });
  return result;
}
export const listSort = (list: Array<any>, options: any): Array<any> => {
  const param: any = {
    sort: 'asc', // 'desc'
    orderKey: 'id',
    isObject: true,
    ...options,
  };
  // 排序方法
  const oFun = (a: any, b: any): number => {
    // 对象数组
    if (param.isObject && param.sort === 'asc') {
      return a[param.orderKey] - b[param.orderKey];
    }
    if (param.isObject && param.sort === 'desc') {
      return b[param.orderKey] - a[param.orderKey];
    }
    if (!param.isObject && param.sort === 'asc') {
      // 非对象数组
      return a - b;
    }
    return b - a;
  };

  return list.sort(oFun);
};

/**
 *
 * @param list
 * @param parentMenuId
 * @returns
 */
export const listToTree = (arr: any[], idKey: string, parentKey: string) => {
  const menuObj: { [x: string]: any } = {};
  arr.forEach((item) => {
    item.children = [];
    menuObj[item[idKey]] = item;
  });
  return arr.filter((item) => {
    if (item[parentKey] !== null) {
      menuObj[item[parentKey]].children.push(item);
      return false;
    }
    return true;
  });
};

/**
 * 获取下拉组件需要的数据形式
 * @param {Array} arr - 原数组
 * @param {Object} [fields = {key: 'name', value: 'id'}] - 转换的key值
 * @returns {Array} - 下拉组件所需的数组形式
 */
export function getSelectOptions(
  arr: Array<any> = [],
  option: {
    title?: string;
    value?: string;
    children?: string;
    key?: string;
  } = { title: 'name', value: 'id', children: 'child', key: 'key' },
  extra = {},
  useKey = false,
  pids = [],
  pid = 0
): Array<any> {
  if (!Array.isArray(arr)) return arr;
  const { title, value, children, key } = option;
  return arr.map((item: any) => {
    const mextra = typeof extra === 'function' ? extra(item) : extra;
    const mpids = pids.concat([item[value || 'id']] as never[]);
    const mvalue = useKey ? key : value;
    const mkey = mpids.join('-');
    const obj = { ...item, ...mextra, key: mkey };
    return {
      ...mextra,
      key: mkey,
      title: obj[title || 'name'],
      label: obj[title || 'name'],
      value: obj[mvalue || 'value'],
      _origin: { ...item },
      pid,
      children: getSelectOptions(
        obj[children || 'child'],
        { title, value, children, key },
        extra,
        useKey,
        mpids,
        obj.id
      ),
    };
  });
}

// 验证是否为blob格式
export const blobValidate = async (data: { text: () => any }) => {
  try {
    const text = await data.text();
    JSON.parse(text);
    return false;
  } catch (error) {
    return true;
  }
};
export function parseTime(time: string | number | Date, pattern?: string) {
  if (arguments.length === 0 || !time) {
    return null;
  }
  const format = pattern || '{y}-{m}-{d} {h}:{i}:{s}';
  let date;
  if (typeof time === 'object') {
    date = time;
  } else {
    if (typeof time === 'string' && /^[0-9]+$/.test(time)) {
      time = parseInt(time, 10);
    } else if (typeof time === 'string') {
      time = time
        .replace(new RegExp(/-/gm), '/')
        .replace('T', ' ')
        .replace(new RegExp(/\.[\d]{3}/gm), '');
    }
    if (typeof time === 'number' && time.toString().length === 10) {
      time *= 1000;
    }
    date = new Date(time);
  }
  const formatObj: { [x: string]: any } = {
    y: date.getFullYear(),
    m: date.getMonth() + 1,
    d: date.getDate(),
    h: date.getHours(),
    i: date.getMinutes(),
    s: date.getSeconds(),
    a: date.getDay(),
  };
  const timeStr = format.replace(
    /{(y|m|d|h|i|s|a)+}/g,
    (result: string | any[], key: string) => {
      let value = formatObj[key];
      // Note: getDay() returns 0 on Sunday
      if (key === 'a') {
        return ['日', '一', '二', '三', '四', '五', '六'][value];
      }
      if (result.length > 0 && value < 10) {
        value = `0${value}`;
      }
      return value || 0;
    }
  );
  return timeStr;
}
/**
 * 获取参数类型
 * @param param 参数
 * @returns 返回字符串的参数类型
 */
export const getParamType = (param: any): string => {
  return Object.prototype.toString.call(param);
};
/**
 * tree转list
 * @param tree tree 数组
 * @param options 转换配置参数
 * @returns 返回 list 数组
 */
export const treeToList = (tree: Array<any>, options: any): Array<any> => {
  // 合并初始配置与用户配置像
  const param: any = {
    childKey: 'children',
    parentKey: 'pid',
    idKey: 'id',
    parentValue: 0,
    isDelChild: false,
    customFn: null,
    ...options,
  };
  let array: Array<any> = [];
  // 遍历数组
  for (let i = 0; i < tree.length; i += 1) {
    let temp: any = tree[i];
    // 获取当前数据下的 child
    const children = temp[param.childKey];
    // 如果有自定义方法 抛给自定义方法处理
    if (getParamType(param.customFn) === '[object Function]') {
      temp = param.customFn(temp);
      if (!temp) {
        throw new Error('请确保customFn函数是否返回数据');
      }
    }
    // 拼接 parent 数据
    temp[param.parentKey] = param.parentValue;
    // 是否删除 child
    if (param.isDelChild) {
      delete temp[param.childKey];
    }
    // 数据加入数组
    array.push(temp);
    // 如果数据 含有 child 递归处理
    if (children) {
      const arr = treeToList(children, {
        ...param,
        parentValue: temp[param.idKey],
      });
      // 合并数组
      array = array.concat(arr);
    }
  }

  return array;
};
export const dataToUrlParams = (data: any): string => {
  let tempUrl = '?';
  const keys = Object.keys(data);
  keys.forEach((key, index) => {
    if (index !== 0) {
      tempUrl += '&';
    }
    tempUrl = `${tempUrl + key}=${data[key]}`;
  });
  return tempUrl;
};

// 根据出生年月获取年龄
export const birthdayToAge = (birthday: any): number => {
  let age = 0;
  // 校验是否传值
  if (birthday) {
    const birthdayTime = new Date(birthday).getTime();
    const nowTime = new Date().getTime();
    // 只有出生日期小于今天才可以计算
    if (birthdayTime <= nowTime) {
      age = parseInt(`${(nowTime - birthdayTime) / (366 * 86400000)}`, 10);
    }
  }

  return age;
};

export default null;
